﻿//功能描述：Dapper帮助类
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using Dapper.Contrib.Extensions;
using Hong.Common.Encryption;
using Microsoft.Extensions.Configuration;
using Z.Dapper.Plus;

namespace Hong.Repository.Repository
{
    public class DapperHelper
    {
        private readonly SecurityStatic _securityStatic;

        public DapperHelper(SecurityStatic  securityStatic)
        {
            _securityStatic=securityStatic;
        }


        #region 映射完成增删改简单操作

        /// <summary>
        /// 映射添加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="sqlAdapter"></param>
        /// <returns></returns>
        public async Task<int> AddAsync<T>(T model, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
        {
            using (var conn = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await conn.InsertAsync<T>(model, transaction, commandTimeout);
            }
        }
        public long Add<T>(T model, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
        {
            using (var conn = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return conn.Insert<T>(model, transaction, commandTimeout);
            }
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="connection"></param>
        /// <param name="entityToUpdate"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public async Task<T> UpdateAsync<T>(T model, IDbTransaction transaction = null, int? commandTimeout = null) where T : class, new()
        {
            using (var conn = new SqlConnection(_securityStatic.Securityinfo()))
            {
                bool b = await conn.UpdateAsync<T>(model, transaction, commandTimeout);
                if (b) { return model; }
                else { return null; }
            }
        }
        public T Update<T>(T model, IDbTransaction transaction = null, int? commandTimeout = null) where T : class, new()
        {
            using (var conn = new SqlConnection(_securityStatic.Securityinfo()))
            {
                bool b = conn.Update<T>(model, transaction, commandTimeout);
                if (b) { return model; }
                else { return null; }
            }
        }

        #endregion


        #region 批量操作数据 (都是同步完成)

        /// <summary>
        /// 批量修改 同步
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="m"></param>
        /// <param name="tablename"></param>
        /// <returns></returns>
        public int ManyUpd<T>(List<T> m, string tablename) where T : class
        {
            try
            {
                DapperPlusManager.Entity<T>().Table(tablename);
                using (var connection = new SqlConnection(_securityStatic.Securityinfo()))
                {
                    connection.BulkUpdate(m);
                    return 1;
                }
            }
            catch (Exception e)
            {
                return -1;
            }
        }

        /// <summary>
        /// 批量添加 同步
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="m">添加的数据</param>
        /// <param name="tablename">表名</param>
        /// <returns></returns>
        public int ManyAdd<T>(List<T> m, string tablename) where T : class
        {
            try
            {
                DapperPlusManager.Entity<T>().Table(tablename);
                using (var connection = new SqlConnection(_securityStatic.Securityinfo()))
                {
                    connection.BulkInsert(m);
                    return 1;
                }
            }
            catch (Exception e)
            {
                return -1;
            }
        }

        #endregion


        #region dapper 基本用法(编写sql语句)

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="sql">查询的sql</param>
        /// <param name="param">替换参数</param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> QueryAsync<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.QueryAsync<T>(sql, param);
            }
        }
        public IEnumerable<T> Query<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return con.Query<T>(sql, param);
            }
        }


        /// <summary>
        /// 查询第一个数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<T> QueryFirstAsync<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.QueryFirstAsync<T>(sql, param);
            }
        }
        public T QueryFirst<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return con.QueryFirst<T>(sql, param);
            }
        }

        /// <summary>
        /// 查询第一个数据没有返回默认值
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<T> QueryFirstOrDefaultAsync<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.QueryFirstOrDefaultAsync<T>(sql, param);
            }
        }
        public T QueryFirstOrDefault<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return con.QueryFirstOrDefault<T>(sql, param);
            }
        }

        /// <summary>
        /// 查询单条数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<T> QuerySingleAsync<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.QuerySingleAsync<T>(sql, param);
            }
        }
        public T QuerySingle<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return con.QuerySingle<T>(sql, param);
            }
        }

        /// <summary>
        /// 查询单条数据没有返回默认值
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<T> QuerySingleOrDefaultAsync<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.QuerySingleOrDefaultAsync<T>(sql, param);
            }
        }
        public T QuerySingleOrDefault<T>(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return con.QuerySingleOrDefault<T>(sql, param);
            }
        }

        /// <summary>
        /// 增删改
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<int> ExecuteAsync(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.ExecuteAsync(sql, param);
            }
        }
        public int Execute(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return con.Execute(sql, param);
            }
        }

        /// <summary>
        /// Scalar获取数据 首行首列
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<object> ExecuteScalarAsync(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.ExecuteScalarAsync(sql, param);
            }
        }
        public object ExecuteScalar(string sql, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return con.ExecuteScalar(sql, param);
            }
        }

        /// <summary>
        /// 带参数的存储过程
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> ExecuteProAsync<T>(string proc, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                return await con.QueryAsync<T>(proc,
                    param);
            }
        }
        public List<T> ExecutePro<T>(string proc, object param = null)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                List<T> list = con.Query<T>(proc,
                    param,
                    null,
                    true,
                    null,
                    CommandType.StoredProcedure).ToList();
                return list;
            }
        }

        #endregion


        #region 执行多条sql语句 使用事务

        /// <summary>
        /// 事务1 - 多条SQL
        /// </summary>
        /// <param name="sqlarr">多条SQL</param>
        /// <param name="param">param</param>
        /// <returns></returns>
        public async Task<int> ExecuteTransactionAsync(string[] sqlarr)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                con.Open();
                using (var transaction = con.BeginTransaction())
                {
                    try
                    {
                        int result = 0;
                        foreach (var sql in sqlarr)
                        {
                            result += await con.ExecuteAsync(sql, null, transaction);
                        }

                        await transaction.CommitAsync();
                        return result;
                    }
                    catch (Exception ex)
                    {
                        transaction.RollbackAsync();
                        return 0;
                    }
                }
                con.Close();
            }
        }
        public int ExecuteTransaction(string[] sqlarr)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                con.Open();
                using (var transaction = con.BeginTransaction())
                {
                    try
                    {
                        int result = 0;
                        foreach (var sql in sqlarr)
                        {
                            result += con.Execute(sql, null, transaction);
                        }

                        transaction.Commit();
                        return result;
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }
                con.Close();
            }
        }

        /// <summary>
        /// 事务2 - 多条sql 声明参数
        ///demo:
        ///dic.Add("Insert into Users values (@UserName, @Email, @Address)",
        ///        new { UserName = "jack", Email = "380234234@qq.com", Address = "上海" });
        /// </summary>
        /// <param name="Key">多条SQL</param>
        /// <param name="Value">param</param>
        /// <returns></returns>
        public async Task<int> ExecuteTransactionAsync(Dictionary<string, object> dic)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                using (var transaction = con.BeginTransaction())
                {
                    try
                    {
                        int result = 0;
                        foreach (var sql in dic)
                        {
                            result += await con.ExecuteAsync(sql.Key, sql.Value, transaction);
                        }
                        transaction.CommitAsync();
                        return result;
                    }
                    catch (Exception ex)
                    {
                        transaction.RollbackAsync();
                        return 0;
                    }
                }
            }
        }
        public int ExecuteTransaction(Dictionary<string, object> dic)
        {
            using (SqlConnection con = new SqlConnection(_securityStatic.Securityinfo()))
            {
                using (var transaction = con.BeginTransaction())
                {
                    try
                    {
                        int result = 0;
                        foreach (var sql in dic)
                        {
                            result += con.Execute(sql.Key, sql.Value, transaction);
                        }

                        transaction.Commit();
                        return result;
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }
            }
        }

        #endregion

    }
}